package com.example.diamond.demo.diamond;

import com.alibaba.druid.pool.DruidDataSource;
import com.taobao.diamond.manager.DiamondManager;
import com.taobao.diamond.manager.ManagerListenerAdapter;
import com.taobao.diamond.manager.impl.DefaultDiamondManager;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.StringReader;
import java.util.Properties;

@Component
public class DiamondDataSource implements FactoryBean<DruidDataSource>, InitializingBean, DisposableBean {
    private final Logger logger = LoggerFactory.getLogger(DiamondDataSource.class);
    @Value("${diamond.group}")
    private String group;
    @Value("${diamond.dataId}")
    private String dataId;
    private Properties props;
    private DruidDataSource druidDataSource;

    @Override
    public void afterPropertiesSet() {
        logger.info("[DiamondDataSource.afterPropertiesSet] Load diamond config to environment start ...");
        DiamondManager manager = new DefaultDiamondManager(group, dataId, new ManagerListenerAdapter() {
            @Override
            public void receiveConfigInfo(String content) {
                reloadContent(content);
            }
        });
        String content = manager.getAvailableConfigureInfomation(5000L);
        reloadContent(content);
        logger.info("[DiamondDataSource.afterPropertiesSet] Load diamond config to environment end.");
    }

    @Override
    public void destroy() {
        if (druidDataSource != null) {
            druidDataSource.close();
        }
    }

    @Override
    public DruidDataSource getObject() {
        return druidDataSource;
    }

    @Override
    public Class<?> getObjectType() {
        return DruidDataSource.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    private void reloadContent(String content) {
        if (StringUtils.isNotEmpty(content)) {
            if (props == null) {
                props = new Properties();
            }
            try {
                props.load(new StringReader(content));
            } catch (IOException e) {
                logger.error("[DiamondDataSource.loadContent] Diamond exception :", e);
            }
        }
        if (druidDataSource == null) {
            druidDataSource = new DruidDataSource();
            druidDataSource.setUrl(props.getProperty("spring.datasource.url"));
            druidDataSource.setUsername(props.getProperty("spring.datasource.username"));
            druidDataSource.setPassword(props.getProperty("spring.datasource.password"));
            druidDataSource.setDriverClassName(props.getProperty("spring.datasource.driver-class-name"));
            druidDataSource.setInitialSize(Integer.parseInt(props.getProperty("spring.datasource.druid.initial-size")));
            druidDataSource.setMaxActive(Integer.parseInt(props.getProperty("spring.datasource.druid.max-active")));
            druidDataSource.setMinIdle(Integer.parseInt(props.getProperty("spring.datasource.druid.min-idle")));
            druidDataSource.setMaxWait(Long.parseLong(props.getProperty("spring.datasource.druid.max-wait")));
            druidDataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(props.getProperty("spring.datasource.druid.time-between-eviction-runs-millis")));
            druidDataSource.setMinEvictableIdleTimeMillis(Long.parseLong(props.getProperty("spring.datasource.druid.min-evictable-idle-time-millis")));
        } else {
            try {
                druidDataSource.restart();
                druidDataSource.setUrl(props.getProperty("spring.datasource.url"));
                druidDataSource.setUsername(props.getProperty("spring.datasource.username"));
                druidDataSource.setPassword(props.getProperty("spring.datasource.password"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
